﻿
/** Digitalfx.tv package */
package tv.digitalfx
{
import caurina.transitions.Tweener;
import pete.tools.Random;
import pete.tools.SplitChannels;
import flash.display.DisplayObject;
import flash.display.BlendMode;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName;

/**
 * @version
 * 0.1
 *
 * @description 
 * Animates the colors of a target DisplayObject disaligning.
 * 
 * @example
 * <pre>
 * var test:Sprite = new Sprite ();
 * <br />
 * var colorError:ColorError = ColorError.getInstance ();
 * colorError.start (test, .5); // Will perform the ColorError animation for exactly 500 miliseconds.
 * </pre>
 */
public class ColorError extends EventDispatcher
{
	/**
	 * Easing equation from Easing.as to calculate tween curvature (By Robert Penner).
	 * @default Easing.EXPO_EASE_IN
	 */
	public static var ease:String = "easeInBounce";
	private static var xx:Object = new Dictionary ();
	
	
	/**
	 * Singleton constructor. Use <code>ColorError.getInstance();</code> instead.
	 */
	public function ColorError ()
	{
		if (getQualifiedClassName (super) == "tv.digitalfx::ColorError")
		{
			if (!allowInstantiation)
			{
				throw new Error("Error: Instantiation failed: Use ColorError.getInstance() instead of new ColorError().");
			}
		}
	}
	
	private static var instance:ColorError = null;
	private static var allowInstantiation:Boolean = false;
	
	/**
	 * Returns the single global instance of this class.
	 */
	public static function getInstance ():ColorError
	{
		if ( ColorError.instance == null )
		{
			ColorError.allowInstantiation = true;
			ColorError.instance = new ColorError ();
			ColorError.allowInstantiation = false;
		}
		return ColorError.instance;
	}
	
	
	
	
	/**
	 * Starts a disaligning animation.
	 * @param target Object to animate.
	 * @param duration Duration of the animation (in seconds).
	 * @param peakFunction Function to call when the animation reaches its Peak.
	 */
	public function start( target:Object, duration:Number = 1, range:Number = 10 ):void
	{
		if ( xx[ target ] == undefined )
		{
			xx[ target ] = new Object ();
			xx[ target ].animated = -1;
			xx[ target ].split = new SplitChannels( target );
		}
		
		if ( xx[ target ].animated == -1 )
		{
			xx[ target ].animated = 0;
			
			xx[ target ].duration = duration/2;
			xx[ target ].split.x = target.x;
			xx[ target ].split.y = target.y;
			
			target.visible = false;
			target.parent.addChild( xx[ target ].split );
			
			var dur:Number = xx[ target ].duration;
			
			// Split
			Tweener.addTween ( xx[target].split.red,
					   { x:		Random.choose (-range, range), 
					     y:		Random.choose (-range, range), 
					     time: 		dur,
					     transition: 	ease } );
			
			Tweener.addTween ( xx[ target ].split.green,
					   { x:		Random.choose ( -range, range ),
					     y:		Random.choose ( -range, range ),
					     time:		dur,
					     transition:	ease } );
			
			Tweener.addTween ( xx[ target ].split.blue,
					   { x:		Random.choose ( -range, range ),
					     y:		Random.choose ( -range, range ),
					     time:		dur,
					     transition:	ease } );
			
			// Return
			Tweener.addTween (xx[ target ].split.red,
					   { x:		0,
					     y:		0,
					     time: 		dur,
					     delay: 		dur * .95,
					     transition:	ease } );
			
			Tweener.addTween (xx[ target ].split.green,
					   { x:		0,
					     y:		0,
					     time:		dur,
					     delay:		dur * .95,
					     transition:	ease } );
			
			Tweener.addTween (xx[ target ].split.blue,
					   { x:		0,
					     y:		0,
					     time:		dur,
					     delay:		dur, 
					     transition:	ease,
					     onComplete:	stop,
					     onCompleteParams:[ target ] } );
		}
	}
	
	
	/**
	 * Stops the disaligning animation of target Object
	 * @param target Animating Object.
	 */
	public function stop( target:Object ):void
	{
		target.parent.removeChild( xx[ target ].split );
		target.visible = true;
		
		xx[ target ].animated = -1;
	}
}
	
}